import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

import '../main.dart';

class CSSNodeData extends ContainerBoxParentData<RenderBox> {
  static Map<String, Widget Function(CSSNodeData)> widgetTypes = {};

  CSSNodeData();

  CSSNodeData.init(Function(CSSNodeData) initFn) {
    initFn(this);
  }

  CSSNodeData.fromJSONObject(dynamic json) {
    for (String key in json) {}
  }

  CSSNodeData.fromJSONArray(dynamic json) {
    type = json[0];
    uuid = json[1];
  }

  String type = '';

  int uuid = 0;

  CSSLocation? location;

  CSSDisplay display = CSSDisplay.inline;

  CSSPosition position = CSSPosition.static;

  CSSMargin? margin;

  CSSBorder? border;

  CSSPadding? padding;

  AlignmentGeometry? alignment;

  CSSBackground? background;

  TextStyle? textStyle;

  Matrix4? transform;

  AlignmentGeometry? transformOrigin;

  Clip? clip;

  dynamic attributes;

  List<CSSNodeData>? children;

  Widget get widget {
    return (widgetTypes[type] ?? widgetTypes['Text']!)(this);
  }

  List<Widget> get childrenWidget {
    return children != null
        ? children!.map((e) => e.widget).toList()
        : <Widget>[];
  }

  // 父节点数据
  CSSNodeData? parent;

  // 渲染大小
  Size size = Size.zero;

  // 字体大小
  double fontSize = 0;

  // 是否独立绘制
  bool isRepaintBoundary = false;

  @override
  // ignore: must_call_super
  void detach() {
    this.parent = null;
  }

  CSSNodeData get relative {
    CSSNodeData target = this;
    CSSNodeData? parent;

    while ((parent = target.parent) != null) {
      if (parent!.position != CSSPosition.static) {
        return parent;
      }

      target = parent;
    }

    return target;
  }
}


class CSSNode extends SingleChildRenderObjectWidget {
  final CSSNodeData data;

  CSSNode(this.data, Widget? child)
      : super(key: ValueKey(data.uuid), child: child);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return CSSNodeRenderBox(data);
  }
}

class CSSNodeRenderBox extends RenderShiftedBox {
  CSSNodeData data;

  CSSNodeRenderBox(this.data) : super(null);

  @override
  bool get isRepaintBoundary => data.isRepaintBoundary;

  @override
  void performLayout() {
    final BoxConstraints constraints = this.constraints;

    data.size = size = Size(200, 100);

    child?.layout(constraints, parentUsesSize: true);
  }

  @override
  void debugAssertDoesMeetConstraints() {}

  @override
  void paint(PaintingContext context, Offset offset) {
    data.background?.paint(context, data);

    super.paint(context, offset);

    data.border?.paint(context, data);
  }
}
